package model;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;


public class JarArtifact extends JavaArtifact {

	private List<ClassArtifact> classArtifacts;
	
	protected JarArtifact(String path) {
		super(path, JavaFileExtension.JAR);
		classArtifacts = new LinkedList<ClassArtifact>();
	}
	
	@Override
	public ClassVersion calculateClassVersion() {
		JarInputStream jarInputStream = null;
		try {
			FileInputStream fileInputStream = new FileInputStream(super.getPath());
			jarInputStream = new JarInputStream(fileInputStream);
			
			JarEntry jarEntry = null;
			while((jarEntry = jarInputStream.getNextJarEntry()) != null) {
				String jarEntryPath = jarEntry.getName();
				if (JavaFileExtension.hasJavaFileExtension(jarEntryPath)) {
					ClassArtifact classArtifact = (ClassArtifact) JavaArtifactFactory.create(jarEntryPath);
					classArtifact.calculateClassVersion(jarInputStream);
					classArtifacts.add(classArtifact);
				}
			}
			
			// TODO multiple class version might exists; 
			// TODO when dummy developer put a single class 
			// TODO that is compiled by another JAVAC
			setClassVersion(classArtifacts.get(0).getClassVersion());
			
			return getClassVersion();
		} catch (IOException e) {
			throw new InvalidJavaArtifactContentException("IO exception occured: " + e.getMessage());
		} finally {
			try {
				if (jarInputStream != null) {
					jarInputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public ClassVersion calculateClassVersion(InputStream inputStream) {
		JarInputStream jarInputStream = null;
		try {
			byte[] buffer = copyToBuffer(inputStream);
			ByteArrayInputStream bufferInputStream = new ByteArrayInputStream(buffer);
			jarInputStream = new JarInputStream(bufferInputStream);
			
			JarEntry jarEntry = null;
			while((jarEntry = jarInputStream.getNextJarEntry()) != null) {
				String jarEntryPath = jarEntry.getName();
				if (JavaFileExtension.hasJavaFileExtension(jarEntryPath)) {
					ClassArtifact classArtifact = (ClassArtifact) JavaArtifactFactory.create(jarEntryPath);
					classArtifact.calculateClassVersion(jarInputStream);
					classArtifacts.add(classArtifact);
					
					// TODO multiple class version might exists; 
					// TODO when dummy developer put a single class 
					// TODO that is compiled by another JAVAC
					setClassVersion(classArtifact.getClassVersion());
				}
			}
			
			return getClassVersion();
		} catch (IOException e) {
			throw new InvalidJavaArtifactContentException("IO exception occured: " + e.getMessage());
		} finally {
			try {
				if (jarInputStream != null) {
					jarInputStream.close();
				}
			} catch (IOException e) {
				throw new InvalidJavaArtifactContentException("IO exception occured: " + e.getMessage());
			}
		}
	}

	public List<ClassArtifact> getClassArtifacts() {
		return classArtifacts;
	}
	
	@Override
	public String toString() {
		String superToString = super.toString();
		superToString += "\r\n#CLASSES#\r\n";
		for (ClassArtifact classArtifact : this.classArtifacts) {
			superToString += classArtifact.toString() + "\r\n";
		}
		
		return superToString;
	}
}
